import {DetailComments} from "@/interface/comment/entity/CommentEntityInterface";
import toast from "@/utils/Toast";

/** yzj 工具 ts */

export class ProcessingData {
  tempArray: any[] = [];
  ARRAY = 'Array';
  OBJECT = 'Object';
  NUMBER = 'Number';
  BOOLEAN = 'Boolean';
  STRING = 'String';
  TYPE_TEMPLATE = {
    '[object Array]': 'Array',
    '[object Object]': 'Object',
    '[object Number]': 'Number',
    '[object Boolean]': 'Boolean',
    '[object String]': 'String'
  }
  /**
   * 过滤数组
   * @param arr 数组数据
   * @param filter 过滤字段
   * @param key 是否有指定的键值
   * @param reload 是否重新刷新
   */
  filterArray = (arr: any[], filter: string, key?: string, reload?: boolean) => {
    this.tempArray = arr;
    let newArr: any[];
    let fs = reload ? this.tempArray : arr, nlwc = filter.toLocaleLowerCase();
    // 监听 filename 输入
    if (filter && filter.trim() !== '') {
      if (key) {
        newArr = fs.filter(f => f[key].toLocaleLowerCase().indexOf(nlwc) !== -1);
      } else {
        newArr = fs.filter(f => f.toLocaleLowerCase().indexOf(nlwc) !== -1);
      }
    } else {
      newArr = this.tempArray;
    }
    return newArr;
  }

  /**
   * 全替换对象里的值
   * @param obj 对象
   * @param replace 替换值
   */
  replaceObj = (obj: object, replace?: any) => {
    for (let key in obj) {
      if (replace) {
        obj[key] = replace
      } else {
        obj[key] = ''
      }
    }
    return obj;
  }


  /**
   * 判断字符串、数组对象数据是否为空
   * @param obj 对象
   * @param isBlank 是否去空格 -- 针对字符串
   */
  isEmpty = (obj: [] | string | object, isBlank?: boolean) => {
    if (obj === null || !obj) {
      return true;
    }
    let typePrototype = Object.prototype.toString.call(obj), type = this.TYPE_TEMPLATE[typePrototype];
    if (type === this.STRING) {
      let txt = obj as string;
      if (isBlank) {
        return txt.trim() === ''
      }
      return txt === '';
    } else if (type === this.ARRAY) {
      let array = obj as [];
      return array.length === 0;
    } else if (type === this.OBJECT) {
      let object = obj as object;
      let booleanArr: boolean[] = [];
      for (let key in object) {
        let data = object[key];
        if (isBlank && typeof (data) === 'string') {
          booleanArr.push(<boolean>(data.trim() !== ''));
          // 如果不存在或者为空则直接返回 true
        } else if (data.length && data.length === 0) {
          booleanArr.push(data.length && data.length === 0);
        }
      }
      return booleanArr.indexOf(true) === -1;
    }
    return true;
  }
}


export class ExecFunction {
  // 记录时间
  recordTime = 0;
  // 记录回滚数据
  data: any | undefined;
  // 是否开启阻塞
  blockingFn = false;

  /**
   * 阻塞方法
   * @param successFn 时间之内指向
   * @param blockingFn 阻塞时执行的方法
   * @param blockageTime 阻塞时间: 返回阻塞剩余时间
   */
  blockageFunction(successFn: () => void, blockingFn: (number: number) => void, blockageTime: number) {
    // 初始化
    let currentTime;
    if (this.recordTime === 0) {
      this.recordTime = new Date().getTime();
      return successFn();
    } else if ((currentTime = new Date().getTime()) - this.recordTime >= blockageTime) {
      // 更新时间
      this.recordTime = new Date().getTime();
      return successFn();
    } else {
      return blockingFn(blockageTime - (currentTime - this.recordTime));
    }
  }

  /**
   * 重置记录时间
   */
  restBlockageTime() {
    this.recordTime = 0;
  }

  /**
   * 记录回滚的数据
   * @param data
   */
  record(data) {
    if (data === null || data === undefined) throw new Error("回滚至目标数据不能为空");
    // 深度拷贝
    this.data = JSON.parse(JSON.stringify(data));
    return this;
  }

  /** 开启阻塞exec */
  blocking() {
    this.blockingFn = true;
    return this;
  }

  /**
   * 执行方法
   * @param fn 执行函数
   * @param failFn 阻塞时函数
   * @param blockageTime 阻塞时间
   */
  async exec(fn: () => void, failFn?: (time) => void, blockageTime?: number) {
    if (this.blockingFn && !blockageTime) throw Error('请设置阻塞时间');
    if (this.blockingFn && failFn && blockageTime) {
      // 初始化
      let currentTime;
      if (this.recordTime === 0) {
        this.recordTime = new Date().getTime();
        return await this.execFn(fn);
      } else if ((currentTime = new Date().getTime()) - this.recordTime >= blockageTime) {
        // 更新时间
        this.recordTime = new Date().getTime();
        return await this.execFn(fn);
      } else {
        failFn(blockageTime - (currentTime - this.recordTime));
      }
    } else {
      return await this.execFn(fn);
    }
  }

  async execFn(fn: () => void) {
    try {
      await fn.call(null);
      return null;
    } catch (e) {
      return this.data;
    }
  }
}
